package com.cmcc.passenger.ui.order

import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.location.Location
import android.location.LocationManager
import android.net.Uri
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Looper
import android.view.View
import android.widget.LinearLayout
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.alibaba.android.arouter.facade.annotation.Route
import com.cmcc.passenger.R
import com.cmcc.passenger.config.PassPath
import com.cmcc.passenger.data.entity.OrderDetail
import com.cmcc.passenger.databinding.ActivityOrderDetialBinding
import com.cmcc.passenger.ui.base.BasicActivity
import com.cmcc.passenger.ui.fragment.AppAlertDialog
import com.cmcc.passenger.ui.main.MainActivity
import com.cmcc.passenger.ui.order.viewmodel.OrderDetailViewModel

import com.cmcc.passenger.util.LocationUtil
import com.cmcc.shared.data.MessageEvent
import com.cmcc.shared.data.PassenMainEvent
import com.cmcc.shared.model.CurrentCoordinates
import com.cmcc.shared.model.DriverCache
import com.cmcc.shared.utils.TextViewUtil.setTextViewByLimit
import com.cmcc.shared.utils.TimeUtils
import com.cmcc.shared.utils.clickWithTrigger
import com.google.android.gms.location.*

import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.*
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.common.eventbus.EventBus
import com.google.maps.android.PolyUtil
import kotlinx.android.synthetic.main.layout_order_detail.view.*
import java.text.SimpleDateFormat
import java.util.*


@Route(path = PassPath.ORDER_DETAIL)
class OrderDetailActivity : BasicActivity(), OnMapReadyCallback {
    private var orderRequest: OrderDetail? = null

    private lateinit var viewModel: OrderDetailViewModel
    private var timer: Timer? = null
    private var mMap: GoogleMap? = null

    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private lateinit var locationRequest: LocationRequest
    private lateinit var locationCallback: LocationCallback
    private var driverInfo = MutableLiveData<DriverCache>()
    private var isDoing: Boolean = false
    private var hasDrawDriverToStart = false
    private var hasDrawStartToEnd = false

    private var countDownTimer: CountDownTimer? = null

    override fun onMapReady(googleMap: GoogleMap) {

        mMap = googleMap
        mMap?.isMyLocationEnabled = true

        val appointLoc = LocationUtil.getInstance().getCurrentLoc()
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(appointLoc, 18f))

        drawRoutes(mMap!!)

    }


    private lateinit var bottomSheetBehavior: BottomSheetBehavior<LinearLayout>

    private var mapFragment: SupportMapFragment? = null

    private lateinit var binding: ActivityOrderDetialBinding

    override fun initialize(savedInstanceState: Bundle?) {


        viewModel = ViewModelProviders.of(this).get(OrderDetailViewModel::class.java)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_order_detial)

        bottomSheetBehavior = BottomSheetBehavior.from(binding.behaviorLayout)
        mapFragment = supportFragmentManager
            .findFragmentById(R.id.map) as SupportMapFragment?

        isDoing = intent.getBooleanExtra("is_doing", false)


        binding.myToolbar.toolbar.setNavigationOnClickListener { finish() }


        binding.locate.clickWithTrigger {
            requestLocationService()
        }

//        if (isDoing) initDoingOrder()


        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

        locationRequest = LocationRequest()
        locationRequest.interval =
            MainActivity.UPDATE_INTERVAL//请求时间间隔
        locationRequest.fastestInterval =
            MainActivity.FASTEST_INTERVAL//最快时间间隔
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                if (locationResult == null) return
                handleLocation(locationResult.lastLocation)
            }
        }
//        //通知首页 刷新接单的按钮
//
//        var  event = MessageEvent()
//        var  passenMainEvent = PassenMainEvent()
//        passenMainEvent.code = 200
//        event.passenMainEvent = passenMainEvent
//        org.greenrobot.eventbus.EventBus.getDefault().post(event);


    }

    /**
     * 请求定位服务
     */
    private fun requestLocationService() {
        val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            requestLocationUpdate()
        }
    }

    /**
     * 请求位置更新
     */
    private fun requestLocationUpdate() {
        fusedLocationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.myLooper()
        )
    }

    /**
     * 获取当前位置的回调方法
     */
    private fun handleLocation(lastLocation: Location) {
        val latLng = LatLng(lastLocation.latitude, lastLocation.longitude)
        mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18f))
        mMap?.isMyLocationEnabled = true

        LocationUtil.getInstance().setCurrentLoc(latLng)

        stopLocationUpdate()
    }

    private fun stopLocationUpdate() {
        fusedLocationClient.removeLocationUpdates(locationCallback)
    }

    override fun onResume() {
        super.onResume()

        val id = intent.getStringExtra("order_id")
        if (id.isNotEmpty()) {
            viewModel.getOrderDetail(id)
            hasDrawDriverToStart = false
            hasDrawStartToEnd = false
        }
    }


    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)

        isDoing = intent?.getBooleanExtra("is_doing", false) ?: false
    }

    /**
     * 每隔5秒获取司机位置
     */
    private fun startTimer() {
        timer = Timer()
        val task = object : TimerTask() {
            override fun run() {
                val status = orderRequest?.status

                runOnUiThread {
                    if(status != 1){
                        mMap?.isMyLocationEnabled = false
                        drawStartToEnd()
                    }
                }

                if(status != 0 && status != 6 && status != 7){
                    getDriverInfo(orderRequest?.driver?.id)
                }
            }
        }
        timer?.schedule(task, 0, 5 * 1000L)
    }

    override fun onPause() {
        stopTimer()
        super.onPause()
    }

    private fun stopTimer() {
        timer?.cancel()
        timer = null
    }

    private fun getDriverInfo(id: String?) {
        if (!id.isNullOrEmpty()) {
            viewModel.getDriverCache(id)
        }
    }

    override fun initObserver(savedInstanceState: Bundle?) {
        viewModel.orderDetail.observe(this, Observer { orderDetail ->
            orderRequest = orderDetail
            initDoingOrder()

            when(orderRequest?.status){
                0->
                    binding.myToolbar.title.text = getString(R.string.order_not_start_title)
                6->
                    binding.myToolbar.title.text = getString(R.string.order_complete_title)
                7->
                    binding.myToolbar.title.text = getString(R.string.order_be_refuse_title)
                else->{
                    binding.myToolbar.title.text = getString(R.string.order_doing_title)
                }
            }

            binding.layoutOrderDetail.createTime.text = orderRequest?.createTime
            binding.layoutOrderDetail.tvScore.text = orderDetail.score


            setTextViewByLimit(
                binding.orderDirection.orderType,
                orderRequest?.type == 1,
                getString(R.string.order_real_time),
                        getString(R.string.order_reservation)
            )

            setTextViewByLimit(
                binding.orderDirection.orderDate,
                orderRequest?.type == 1,
                getString(R.string.trip_time),
                getString(R.string.passenger_order_time_title, orderRequest?.startTime)
            )

            binding.orderDirection.directionStart.text =
                getString(R.string.passenger_origin) + orderRequest?.startAddress
            binding.orderDirection.directionEnd.text =
                getString(R.string.passenger_destination) + orderRequest?.endAddress
            binding.orderRemarks.orderRemarks1.text =
                getCatTypeName(orderRequest?.carCategory?.name)
            binding.orderRemarks.orderRemarks3.text =
                        getTunnelName(orderRequest?.tunnel?.name)
            binding.orderRemarks.orderRemarks2.text =
                        getStationName(orderRequest?.stationIndex)

            binding.orderRemarks.remarkCount.text = getRemark(orderRequest?.remark)

            binding.layoutOrderDetail.driverName.text = orderRequest?.driver?.name
            binding.layoutOrderDetail.carNumber.text =
                getString(R.string.number_card_number_title) + orderRequest?.driverCarIdCard
            binding.orderNumber.text =
                getString(R.string.order_number_title) + orderRequest?.id

            if (orderRequest?.driver?.headPortraitAddress != null) {
                binding.layoutOrderDetail.avatarUrl = orderRequest?.driver?.headPortraitAddress
            }


            val bountyFee = orderRequest?.bountyFee
            if (!bountyFee.isNullOrEmpty()) {
                binding.orderTip.orderRemarks.text =
                    getString(R.string.passenger_order_tip) + bountyFee
            } else {
                binding.orderTip.orderRemarks.text =
                    getString(R.string.passenger_order_tip) + "0.00"
            }

            if (orderRequest?.status == 6) {//订单已完成时，绘制起点到终点的位置
                binding.navigation.visibility = View.GONE
                drawStartToEnd()

                stopTimer()
                if (isDoing) {
                    finish()
                }
            } else {
                startTimer()
            }

            binding.viewModel = viewModel

            mapFragment?.getMapAsync(this)


        })



        viewModel.driverCache.observe(this, Observer { driver ->
            driverInfo.value = driver
            val status = orderRequest?.status

            if (status == 1) {
                drawDriverToStart()
            }

            if(status != 0 && status != 6 && status != 7){
                drawDriverLocation(driver.currentCoordinates)
            }
        })


        viewModel.duration.observe(this, Observer {
            val time = it.replace("hours", getString(R.string.hour))
                .replace("hour", getString(R.string.hour))
                .replace("mins", getString(R.string.minutes))
                .replace("min", getString(R.string.minutes))
                .replace(" ", "")
            when (orderRequest?.status) {
                1 ->
                    binding.layoutOrderDetail.message.text =
                        getString(R.string.passenger_driver_come) + ", " +
                                getString(R.string.predict) + time +
                                getString(R.string.arrive)
                2 ->
                    binding.layoutOrderDetail.message.text =
                        getString(R.string.passenger_driver_go) + ", " +
                                getString(R.string.predict) + time +
                                getString(R.string.arrive)
            }

        })

        viewModel.directionCode.observe(this, Observer { code ->
            if (code == 1) {
                when (orderRequest?.status) {
                    1 ->
                        binding.layoutOrderDetail.message.text =
                            getString(R.string.passenger_driver_come)
                    2 ->
                        binding.layoutOrderDetail.message.text =
                            getString(R.string.passenger_driver_go)
                }

                var startLatLng: LatLng
                var endLatLng: LatLng
                if (orderRequest?.status == 6) {
                    startLatLng = LatLng(
                        orderRequest?.startCoordinates?.latitude ?: 0.0,
                        orderRequest?.startCoordinates?.longitude ?: 0.0
                    )
                    endLatLng = LatLng(
                        orderRequest?.endCoordinates?.latitude ?: 0.0,
                        orderRequest?.endCoordinates?.longitude ?: 0.0
                    )
                } else if (orderRequest?.status == 1) {
                    startLatLng = LatLng(
                        driverInfo.value?.currentCoordinates?.y ?: 0.0,
                        driverInfo.value?.currentCoordinates?.x ?: 0.0
                    )
                    endLatLng = LatLng(
                        orderRequest?.startCoordinates?.latitude ?: 0.0,
                        orderRequest?.startCoordinates?.longitude ?: 0.0
                    )
                } else {
                    startLatLng = LatLng(
                        driverInfo.value?.currentCoordinates?.y ?: 0.0,
                        driverInfo.value?.currentCoordinates?.x ?: 0.0
                    )
                    endLatLng = LatLng(
                        orderRequest?.endCoordinates?.latitude ?: 0.0,
                        orderRequest?.endCoordinates?.longitude ?: 0.0
                    )

                }

                var points: MutableList<LatLng>? = ArrayList()
                points?.add(startLatLng)
                points?.add(endLatLng)

                zoomRoute(mMap, points)

                val status = orderRequest?.status

                mMap?.addMarker(
                    MarkerOptions().position(startLatLng).icon(
                        if (status == 1)
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_car_red)
                        else
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_start_point)
                    )
                )

                mMap?.addMarker(
                    MarkerOptions().position(endLatLng).icon(
                        if (status == 1)
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_start_point)
                        else
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_end_point)
                    )
                )
            }
        })
    }

    private fun drawDriverToStart() {
        if (!hasDrawDriverToStart) {//是否绘制过司机到起点的路线
            queryRoute(
                driverInfo.value?.currentCoordinates?.y.toString(),
                driverInfo.value?.currentCoordinates?.x.toString(),
                orderRequest?.startCoordinates?.latitude.toString(),
                orderRequest?.startCoordinates?.longitude.toString()
            )
        }
    }

    private fun drawStartToEnd() {
        if (!hasDrawStartToEnd) {
            queryRoute(
                orderRequest?.startCoordinates?.latitude.toString(),
                orderRequest?.startCoordinates?.longitude.toString(),
                orderRequest?.endCoordinates?.latitude.toString(),
                orderRequest?.endCoordinates?.longitude.toString()
            )
        }
    }

    private var driverMarker: Marker? = null

    private fun drawDriverLocation(coordinates: CurrentCoordinates) {
        driverMarker?.remove()
        driverMarker = mMap?.addMarker(
            MarkerOptions().position(LatLng(coordinates.y, coordinates.x)).icon(
                BitmapDescriptorFactory.fromResource(R.drawable.ic_car_red)
            )
        )
    }

    private fun getCatTypeName(name: String?): String {
        return getString(R.string.passenger_car_type_with_colon) + if (name == null) getString(R.string.passenger_any_with_space) else "$name "
    }

    private fun getTunnelName(name: String?): String {
        return getString(R.string.passenger_tunnel_with_colon) + if (name == null) getString(R.string.passenger_any_with_space) else "$name "
    }

    private fun getStationName(name: Int?): String {
        return getString(R.string.passenger_station_with_colon) + if (name == null || name == 0) getString(R.string.passenger_any_with_space) else "$name "
    }

    private fun getRemark(name: String?): String {
        return getString(R.string.passenger_remark_with_colon) + if (name == null) getString(R.string.none_with_space) else "$name"
    }


    private fun initDoingOrder() {
        binding.behaviorLayout.phone_call.setImageResource(R.drawable.ic_call)

        val status = orderRequest?.status
        if(status != 0) {
            countDownTimer?.cancel()
            binding.layoutOrderDetail.message.text = ""
        }
        when (status) {
            0 ->{
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_clock)
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_colorAccents))
                binding.layoutOrderDetail.message.text = getString(R.string.order_status_receiving)

                val isOrderInProgress = isOrderInProgress(status?:0,orderRequest?.startTime ?: "")

                if(isOrderInProgress){
                    binding.layoutOrderDetail.message.text =
                        getOffTimeGap(this, orderRequest?.startTime ?: "")

                    countDownTimer = object : CountDownTimer(30 * 60 * 1000L, 1000L) {
                        override fun onTick(millisUntilFinished: Long) {
                            binding.layoutOrderDetail.message.text =
                                getOffTimeGap(this@OrderDetailActivity, orderRequest?.startTime ?: "")
                        }

                        override fun onFinish() {

                        }
                    }.start()
                }else{
                    binding.layoutOrderDetail.message.text =
                        TimeUtils.getOverTimeGap(this, orderRequest?.startTime ?: "")

                    countDownTimer = object : CountDownTimer(60 * 60 * 1000L, 1000L) {
                        override fun onTick(millisUntilFinished: Long) {
                            binding.layoutOrderDetail.message.text =
                                TimeUtils.getOverTimeGap(this@OrderDetailActivity, orderRequest?.startTime ?: "")
                        }

                        override fun onFinish() {

                        }
                    }.start()
                }

            }
            1 -> {
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_clock)
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_colorAccents))
                binding.layoutOrderDetail.message.text = getString(R.string.order_status_receiving)
            }
            2 -> {
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_colorAccents))
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_clock)
                binding.layoutOrderDetail.message.text =
                    getString(R.string.order_status_going_destination)
            }
            3, 4 -> {
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_light_green))
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_trip_end)
                binding.layoutOrderDetail.message.text =
                    getString(R.string.order_status_order_paying)
            }
            5 -> {
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_light_green))
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_trip_end)
                binding.layoutOrderDetail.message.text = getString(R.string.order_status_complete)
            }
            6 -> {
                binding.layoutOrderDetail.message.setTextColor(resources.getColor(R.color.passenger_dark_gray))
                binding.layoutOrderDetail.orderStatus.setImageResource(R.drawable.ic_order_end)
                binding.layoutOrderDetail.message.text = getString(R.string.passenger_order_success)
            }

        }

        binding.layoutOrderDetail.phoneCall.clickWithTrigger {

            AppAlertDialog(this).setContent(getString(R.string.call_driver_message))
                .setNavigation(getString(R.string.cancel), null)
                .setPositive(getString(R.string.make_sure),
                    View.OnClickListener {
                        val data = Uri.parse("tel:${orderRequest?.driver?.phone}")
                        val intent = Intent(Intent.ACTION_DIAL, data)
                        startActivity(intent)
                    }).show()

        }
    }

    fun getOffTimeGap(context: Context, startTime: String): String {
        var format: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        var startDate: Date = format.parse(startTime)

        var nowTime: Date = Date()
        var timeGap = startDate.time - nowTime.time
        return if (timeGap > 0) {
            TimeUtils.getOffTimeGap(context, startTime)
        } else {
            context.getString(com.cmcc.shared.R.string.book_time_come)
        }
    }

    private fun isOrderInProgress(status: Int, startTime: String): Boolean {
        if (status == 0 && !startTime.isNullOrEmpty()) {
            val format: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            val startDate: Date = format.parse(startTime)

            val nowTime: Date = Date()
            val timeGap = startDate.time - nowTime.time
            if (timeGap > 0) {
                return false
            }
        }
        return true
    }

    /**
     * 请求路线
     */
    private fun queryRoute(
        startLatitude: String,
        startLongitude: String,
        endLatitude: String,
        endLongitude: String
    ) {
        viewModel.getDirection(
            "$startLatitude,$startLongitude",
            "$endLatitude,$endLongitude"
        )
    }


    /**
     * 绘制路线到谷歌地图
     */
    private fun drawRoutes(map: GoogleMap) {
        viewModel.direction.observe(this, Observer {
            val decodedPath = PolyUtil.decode(it) //来源Google Map Util
            val lineOptions = PolylineOptions()
            lineOptions.addAll(decodedPath) //添加路线
            lineOptions.color(Color.parseColor("#0AC6A2")) //线条设置
            lineOptions.jointType(JointType.ROUND)
            lineOptions.width(15f)
            map.clear()
            map.addPolyline(lineOptions)

            val status = orderRequest?.status
            if (status == 1) {
                hasDrawDriverToStart = true
            } else {
                hasDrawStartToEnd = true
            }

            if (decodedPath.size > 2) {
                zoomRoute(mMap, decodedPath)

                mMap?.addMarker(
                    MarkerOptions().position(decodedPath[0]).icon(
                        if (status == 1)
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_car_red)
                        else
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_start_point)
                    )
                )

                mMap?.addMarker(
                    MarkerOptions().position(decodedPath[decodedPath.size - 1]).icon(
                        if (status == 1)
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_start_point)
                        else
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_end_point)
                    )
                )

                mMap?.setOnCameraIdleListener { }
            }
        })
    }

    /**
     * Zooms a Route (given a List of LalLng) at the greatest possible zoom level.
     *
     * @param googleMap: instance of GoogleMap
     * @param lstLatLngRoute: list of LatLng forming Route
     */
    private fun zoomRoute(googleMap: GoogleMap?, lstLatLngRoute: List<LatLng>?) {

        if (googleMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return

        val boundsBuilder = LatLngBounds.Builder()
        for (latLngPoint in lstLatLngRoute)
            boundsBuilder.include(latLngPoint)

        val routePadding = 100
        val latLngBounds = boundsBuilder.build()

        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, routePadding))
    }


}